classdef HighpassSGM < Cell
    properties
        Q0;
        K;
        n;
        m;
        k;
    end
    
    methods 
        function this = HighpassSGM(poles, zeros, g)
            this.Name = 'SGM HighpassNotch';
            this.Poles = poles;
            this.Zeros = zeros;
            this.Gain = g;
            wp = abs(poles(1));
            wz = abs(zeros(1));
            [alpha ~] = cart2pol(real(poles(1)), imag(poles(1)));
            Q = abs(1./(2*sin(abs(alpha-pi/2))));
            this.calcCell(wp,wz,Q,g);
            this.ImagePath = 'Stages Schematics/Sedra_HPNotch.png';
        end
        
        function calcCell(obj,wp,wz,Q,g)
            Qaux = [1/3,0.3,0.2,0.1];
            obj.error = 1;
            for k = 1: length(Qaux)
                Q0 = Q*Qaux(k);
                K = 1 + (1/(2*Q0^2))*(1-Q0/Q);
                k = g*(wz/wp)^2/(1-Q0/Q);
                n = k*(1-Q0/(K*Q));
                m = k*((K-1)/K)*(1+2*Q0^2*(wp/wz)^2);
                if (m < 1) && (k < 1) && (n < 1)
                    obj.error = 0;
                    break
                end
            end
            
            if ~obj.error
                resist(3) = 1e3;
                raux = resist(3)/(K-1);
                if wp < 63
                    caux = 1e-6;
                else
                    if wp < 630
                        caux = 100e-9;
                    else
                        if wp < 6300
                            caux = 10e-9;
                        else
                            if wp < 63000
                                caux = 1e-9;
                            else
                                if wp < 630000
                                    caux = 100e-12;
                                else 
                                    caux = 56e-12;
                                end
                            end
                        end
                    end
                end

                resist(1) = raux/(1-k);
                resist(2) = raux/k;
                raux = 1/(2*Q0*wp*caux);
                resist(6) = raux;
                raux = raux*(4*Q0^2);
                resist(4) = raux/(1-n);
                resist(5) = raux/n;
                obj.Resists = resist;
                cap(1) = caux;
                cap(2) = (1-m)*caux;
                cap(3) = m*caux;
                obj.Caps = cap;
                %Sensibilidad de wp
                sens(1) = 0;
                sens(2) = 0;
                sens(3) = 0;
                sens(4) = n/2-0.5;
                sens(5) = -n/2;
                sens(6) = -0.5;
                sens(7) = -0.5;
                sens(9) = m/2-0.5;
                sens(8) = -m/2;
                obj.Senswp = sens;
                %Sensibilidad de Q
                sens(1) = -(2*Q0^2*(k-1))/(2*Q0^2-1);
                sens(2) = 2*k*Q0^2/(2*Q0^2-1);
                sens(3) = -2*Q0^2/(2*Q0^2-1);
                sens(4) = (n+(2*n-2)*Q0^2-1)/(4*Q0^2-2);
                sens(5) = -(2*n*Q0^2+n)/(4*Q0^2-2);
                sens(6) = (2*Q0^2+1)/(4*Q0^2-2);
                sens(7) = -Q0^2/(2*Q0^2-1);
                sens(9) = -(Q0^2*(m-1))/(2*Q0^2-1);
                sens(8) = Q0^2*m/(2*Q0^2-1);
                obj.SensQ = sens;
                %Sensibilidad de Wz
                sens(1) = (k*(m-n)*(k-1)/(2*(k-2*m)*(k-2*n)));
                sens(2) = -((k*(m-n)*(k-2))/(2*(k-2*m)*(k-2*n)));
                sens(3) = k*(m/2-n/2)/(2*k*m+2*k*n-4*m*n-k^2);
                sens(4) = k*(n-1)/(2*(k-2*n));
                sens(5) = -n*(k-2)/(2*(k-2*n));
                sens(6) = -0.5;
                sens(7) = -0.5;
                sens(8) = -m*(k-2)/(2*(k-2*m));
                sens(9) = k*(m-1)/(2*(k-2*m));
                obj.Senswz = sens;
                %Sensibilidad Ginf
                sens(1) = m*(1-k)/(k-2*m);
                sens(2) = -k*(1-m)/(k-2*m);
                sens(3) = (k-m)/(k-2*m);
                sens(4) = 0;
                sens(5) = 0;
                sens(6) = 0;
                sens(7) = 0;
                sens(8) = -2*m*(1-m)/(k-2*m);
                sens(9) = -2*m*(m-1)/(k-2*m);
                obj.SensG = sens;

                obj.K = K;
                obj.m = m;
                obj.n = n;
                obj.k = k;
                obj.Q0 = Q0;
                
                obj.error = ~obj.validateComponents(obj.Resists,obj.Caps);
            end
            
        end
        
        function componentChange(obj, component, value)
            obj.error = 0;
            caps = obj.Caps;
            resists = obj.Resists;
            switch component
                case 1
                    obj.Resists(1) = value;
                    raux = obj.Resists(1)*(1 - obj.k);
                    obj.Resists(2) = raux/obj.k;
                    obj.Resists(3) = raux*(obj.K - 1);
                case 2
                    obj.Resists(2) = value;
                    raux = obj.Resists(2)*obj.k;
                    obj.Resists(1) = raux/(1 - obj.k);
                    obj.Resists(3) = raux*(obj.K - 1);
                case 3
                    obj.Resists(3) = value;
                    raux = obj.Resists(3)/(obj.K - 1);
                    obj.Resists(1) = raux/(1 - obj.k);
                    obj.Resists(2) = raux/obj.k;
                case 4
                    wp = abs(obj.Poles(1));
                    obj.Resists(4) = value;
                    raux = obj.Resists(4)*(1-obj.n);
                    obj.Resists(5) = raux/obj.n;
                    obj.Resists(6) = raux;
                    obj.Caps(1) = 1/(2*obj.Q0*wp*raux);
                    obj.Caps(2) = (1-obj.m)*obj.Caps(1);
                    obj.Caps(3) = obj.m*obj.Caps(1);
                case 5
                    wp = abs(obj.Poles(1));
                    obj.Resists(5) = value;
                    raux = obj.Resists(5)*obj.n;
                    obj.Resists(4) = raux/(1 - obj.n);
                    obj.Resists(6) = raux;
                    obj.Caps(1) = 1/(2*obj.Q0*wp*raux);
                    obj.Caps(2) = (1 - obj.m)*obj.Caps(1);
                    obj.Caps(3) = obj.m*obj.Caps(1);
                case 6
                    wp = abs(obj.Poles(1));
                    raux = value;
                    obj.Resists(6) = raux;
                    obj.Caps(1) = 1/(2*obj.Q0*wp*raux);
                    obj.Caps(2) = (1 - obj.m)*obj.Caps(1);
                    obj.Caps(3) = obj.m*obj.Caps(1);
                    obj.Resists(4) = raux/(1 - obj.n);
                    obj.Resists(5) = raux/obj.n;
                case 7
                    wp = abs(obj.Poles(1));
                    obj.Caps(1) = value;
                    obj.Caps(2) = (1 - obj.m)*value;
                    obj.Caps(3) = obj.m*value;
                    raux = 1/(2*obj.Q0*wp*value);
                    obj.Resists(6) = raux;
                    raux = raux*(4*obj.Q0^2);
                    obj.Resists(4) = raux/(1 - obj.n);
                    obj.Resists(5) = raux/obj.n;
                case 8
                    wp = abs(obj.Poles(1));
                    obj.Caps(2) = value;
                    obj.Caps(1) = obj.Caps(2)/(1 - obj.m);
                    obj.Caps(3) = obj.m*obj.Caps(1);
                    raux = 1/(2*obj.Q0*wp*obj.Caps(1));
                    obj.Resists(6) = raux;
                    raux = raux*(4*obj.Q0^2);
                    obj.Resists(4) = raux/(1 - obj.n);
                    obj.Resists(5) = raux/obj.n;
                    
                case 9
                    wp = abs(obj.Poles(1));
                    obj.Caps(3) = value;
                    obj.Caps(1) = obj.Caps(3)/obj.m;
                    obj.Caps(2) = obj.Caps(1)*(1 - obj.m);
                    raux = 1/(2*obj.Q0*wp*obj.Caps(1));
                    obj.Resists(6) = raux;
                    raux = raux*(4*obj.Q0^2);
                    obj.Resists(4) = raux/(1 - obj.n);
                    obj.Resists(5) = raux/obj.n;
            end
            
            status = obj.validateComponents(obj.Resists,obj.Caps);
            if ~status
                obj.error = 0;
                obj.Resists = resists;
                obj.Caps = caps;
            end
        end
    end
end
